package com.ojoin.ojoin.eb_spider.utils;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author 张锐敏
 * @version V1.0
 * @description
 */
public class HttpUtils {

    private static Logger logger = Logger.getLogger(HttpUtils.class);


    public static String get(String uri) throws IOException {
        CloseableHttpClient httpclient = getClient(uri);
        HttpGet httpMethod = new HttpGet(uri);
        return praseResponse(httpclient,httpMethod);
    }

    public static String get(String uri,Map<String,String> params) throws IOException {
        if(params != null && !params.isEmpty()){
            StringBuffer buffer = null;
            if(uri.contains("?")){
                if(!uri.endsWith("&")){
                    buffer = new StringBuffer("&");
                }else{
                    buffer = new StringBuffer();
                }
            }else{
                buffer = new StringBuffer("?");
            }

            Iterator<Map.Entry<String,String>> iterator = params.entrySet().iterator();
            while(iterator.hasNext()){
                Map.Entry<String,String> entrySet = iterator.next();
                buffer.append(entrySet.getKey()).append("=").append(URLEncoder.encode(entrySet.getValue(),"UTF-8")).append("&");
            }
            uri += buffer.substring(0,buffer.length()-1);
        }
        logger.debug(uri);
        String result = get(uri);
        logger.debug(result);
        return result;
    }


    public static String post(String uri,Map<String,String> params) throws IOException {

        CloseableHttpClient httpclient = getClient(uri);
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("").build();
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setConfig(requestConfig);
        if(params != null && params.size() > 0){
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            for(Map.Entry<String, String> entry:params.entrySet()){
                String key = entry.getKey();
                Object value = entry.getValue();
                if(value instanceof String){
                    nvps.add(new BasicNameValuePair(key,(String)value));
                }else if(value instanceof List){
                    for(Object v:(List)value){
                        if(v instanceof String){
                            nvps.add(new BasicNameValuePair(key,(String)value));
                        }else {
                            logger.error("error value :" + v + " which key is " + key);
                        }
                    }
                }else{
                    logger.warn("unsupport type");
                }
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps,Consts.UTF_8));
        }

        return praseResponse(httpclient, httpPost);
    }

    public static String post(String uri,String entry) throws IOException {
        Header[] headers = null;
        return post(uri, entry, headers);
    }

    public static String post(String uri, HttpEntity entry) throws IOException {
        Header[] headers = null;
        return post(uri, entry, headers);
    }

    public static String post(String uri,String entry,Header header) throws IOException {
        Header[] headers = null;
        if(header != null){
            headers = new Header[]{header};
        }
        return post(uri, entry, headers);
    }

    private static CloseableHttpClient getClient(String uri){
        CloseableHttpClient httpclient = null;
        if(uri.toLowerCase().startsWith("https")){
            SSLConnectionSocketFactory socketFactory = createSSLConnSocketFactory();
            Registry registry = RegistryBuilder
                    .create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", socketFactory).build();
            httpclient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager(registry)).build();
        }else{
            httpclient = HttpClients.createDefault();
        }
        return httpclient;
    }



    public static String post(String uri, String entry, Header[] headers) throws IOException{
        String result = null;
        if(StringUtils.isNotBlank(uri)){
            CloseableHttpClient httpclient = getClient(uri);

            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("").build();
            HttpPost httpPost = new HttpPost(uri);

            httpPost.setConfig(requestConfig);
            if(headers != null){
                httpPost.setHeaders(headers);
            }

            if(StringUtils.isNotBlank(entry)){
                StringEntity  reqEntity  = new StringEntity(entry,Consts.UTF_8);
                httpPost.setEntity(reqEntity);
            }
            result = praseResponse(httpclient, httpPost);
        }

        return result;
    }

    public static String post(String uri, HttpEntity entry, Header[] headers) throws IOException {
        String result = null;
        if (StringUtils.isNotBlank(uri)) {
            CloseableHttpClient httpclient = getClient(uri);

            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("").build();
            HttpPost httpPost = new HttpPost(uri);

            httpPost.setConfig(requestConfig);
            if (headers != null) {
                httpPost.setHeaders(headers);
            }

            httpPost.setEntity(entry);

            result = praseResponse(httpclient, httpPost);
        }

        return result;
    }

    public static String post(String uri,String entry,SSLConnectionSocketFactory sslsf) throws IOException {

        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("").build();
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setConfig(requestConfig);
        if(StringUtils.isNotBlank(entry)){
            StringEntity  reqEntity  = new StringEntity(entry,Consts.UTF_8);
            httpPost.setEntity(reqEntity);
        }

        return praseResponse(httpclient, httpPost);
    }

    /**
     *
     * @param httpClient
     * @param httpMethod
     * @return
     */
    private static String praseResponse(CloseableHttpClient httpClient, HttpUriRequest httpMethod){
        String result = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpMethod);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                HttpEntity entity = response.getEntity();
                if (entity != null){
                    result = EntityUtils.toString(entity, Consts.UTF_8);
                }
                EntityUtils.consume(entity);
                return result;
            }
            response.close();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private static byte[] prase(CloseableHttpClient httpClient, HttpUriRequest httpMethod){
        byte[] result = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpMethod);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                HttpEntity entity = response.getEntity();
                if (entity != null){
                        result = EntityUtils.toByteArray(entity);
                }
                EntityUtils.consume(entity);
                return result;
            }
            response.close();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static byte[] download(String url){
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpMethod = new HttpGet(url);
        return prase(httpclient, httpMethod);
    }

    /*****
     *  专门用来下载微信上图片
     * @param httpClient
     * @param httpMethod
     * @return
     */
    private static byte[] wxPrase(CloseableHttpClient httpClient, HttpUriRequest httpMethod){
        byte[] result = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpMethod);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                HttpEntity entity = response.getEntity();
                System.out.println("contentLength---->"+entity.getContentLength());
                Header header=entity.getContentType();
                if (entity != null){
                    if (header.getValue().contains("image/")){
                        result = EntityUtils.toByteArray(entity);
                    }
                }
                EntityUtils.consume(entity);
            }
            response.close();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            logger.error("http接口调用异常：url is::" + e.toString(), e);
            System.out.println("连接超时----->:" + e.toString());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("http接口调用异常：url is::" + e.toString(), e);
            System.out.println("连接超时----->:" + e.toString());
        }
        return result;
    }

    public static byte[] wxImgDownload(String url){
        RequestConfig requestConfig= RequestConfig.custom()
                .setSocketTimeout(50000)
                .setConnectionRequestTimeout(50000)
                .setConnectTimeout(50000)
                .build();
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpMethod = new HttpGet(url);
        httpMethod.setConfig(requestConfig);
        return wxPrase(httpclient, httpMethod);
    }

    public static byte[] wxImgDownload(String url,Map<String,String> map)throws Exception
    {
        String newUrl = getUrl(url,map);
        return wxImgDownload(newUrl);
    }

    public static String getUrl(String url, Map<String, String> params) throws Exception {
        if (null!=params && !params.isEmpty())
        {
            StringBuffer sb;
            if (url.contains("?"))
            {
                if (!url.endsWith("&")){
                    sb=new StringBuffer("&");
                }else{
                    sb=new StringBuffer();
                }
            }else{
                sb=new StringBuffer("?");
            }
            for (Map.Entry<String,String> entry:params.entrySet())
            {
                sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(),"UTF-8")).append("&");
            }
            url+=sb.deleteCharAt(sb.length()-1);
        }
        return url;
    }




    /**
     * 创建SSL安全连接,忽略服务器证书，采用信任机
     * http://blog.csdn.net/liang100k/article/details/52768352
     * @return
     */
    private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
        SSLConnectionSocketFactory socketFactory = null;
        try {
            /*

            InputStream ksis = new FileInputStream(new File(keyStoreFile));// 私钥证书
            InputStream tsis = new FileInputStream(new File(trustStoreFile));// 信任证书库
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(ksis, keyStorePass.toCharArray());
            KeyStore ts = KeyStore.getInstance("JKS");
            ts.load(tsis, trustStorePass.toCharArray());
            // 如果有 服务器证书
            .loadKeyMaterial(ks, keyStorePass.toCharArray())
            .loadTrustMaterial(ts, new TrustSelfSignedStrategy())
            */

            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();



            //socketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
            socketFactory = new SSLConnectionSocketFactory(sslContext);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        return socketFactory;
    }

    /**
     * 根据资源Url地址进行上传
     *
     * @param
     * @return
     */
    public static String uploadMediaToWeiXin(String sourceuUrl, String fileName, String token, String type, String wechatUrl) throws IOException {
        // 一个网络图片地址
        //String url = "http://pic6.huitu.com/res/20130116/84481_20130116142820494200_1.jpg";

        logger.info("sourceuUrl:" + sourceuUrl + "--------fileName:" + fileName + "--------type:" + type);
        byte[] bytes = HttpUtils.download(sourceuUrl);

        ByteArrayPartSource bs = new ByteArrayPartSource(fileName, bytes);

        Part p1 = new StringPart("access_token", token);
        Part p2 = new StringPart("type", type);
        Part p3 = new FilePart(fileName, bs);
        Part[] parts = {p1, p2, p3};
        PostMethod httpPost = new PostMethod(wechatUrl);

        MultipartRequestEntity me = new MultipartRequestEntity(parts, httpPost.getParams());
        httpPost.setRequestEntity(me);
        //result = HttpUtils.post(realUrl,ine);
        HttpClient client = new HttpClient();

        int status = client.executeMethod(httpPost);

        String result = null;
        if (status == 200) {
            result = httpPost.getResponseBodyAsString();
            logger.info("result:" + result);
        } else {
            new RuntimeException("status=" + status);
        }
        return result;
    }
}
